package com.google.code.chaotic.server;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;

import javax.jdo.PersistenceManager;
import javax.jdo.Query;
import javax.jdo.Transaction;

import com.google.code.chaotic.ConversionUtil;
import com.google.code.chaotic.dto.CommuterDto;
import com.google.code.chaotic.dto.LatLonDto;
import com.google.code.chaotic.model.Commuter;
import com.google.code.chaotic.model.CommutingHabit;
import com.google.code.chaotic.model.LatLon;
import com.google.code.chaotic.rpc.CommuterSvc;
import com.google.code.chaotic.shared.AuthException;
import com.google.gwt.user.client.rpc.InvocationException;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

//

/**
 * @uml.dependency supplier="com.google.code.chaotic.dto.CommuterDto"
 */
public class CommuterSvcImpl extends RemoteServiceServlet //
		implements CommuterSvc {

	// @PersistenceUnit(unitName = "backTierWebLocal")
	// private EntityManagerFactory emf;

	// @PersistenceContext(unitName = "backTierWebJTA", type = TRANSACTION)
	// private EntityManager em;

	@Override
	public String createCommuter(String sessionId, CommuterDto dto)
			throws AuthException {

		// EntityManager em = EmFactory
		// .getEntityManager(getThreadLocalRequest());
		PersistenceManager pm = PmFactory.get().getPersistenceManager();
		Transaction tx = pm.currentTransaction();
		try {
			tx.begin();
			// String id = createCommuter(dto, em);
			String id = createCommuter(dto, pm);
			tx.commit();
			return id;

		} finally {
			// em.close();
			if (tx.isActive())
				tx.rollback();
			pm.close();
		}
	}

	public String createCommuter(CommuterDto dto, //
			/* EntityManager em */
			PersistenceManager pm) {

		Commuter entity = ConversionUtil.dtoToEntity(dto);
		pm.makePersistent(entity);
		dto.setId(entity.getId());
		return dto.getId();
	}

	@Override
	public void updateCommuter( //
			String sessionId, CommuterDto dto, boolean updatePass) //
			throws AuthException {

		// EntityManager em = EmFactory
		// .getEntityManager(getThreadLocalRequest());
		PersistenceManager pm = PmFactory.get().getPersistenceManager();
		try {
			// updateCommuter(dto, em, updatePass);
			updateCommuter(dto, pm, updatePass);

		} finally {
			// em.close();
			pm.close();
		}
	}

	public void updateCommuter(CommuterDto dto,//
			/* EntityManager em */
			PersistenceManager pm, //
			boolean updatePass) {

		Commuter entity = ConversionUtil.dtoToEntity(dto);
		// EntityTransaction tx = em.getTransaction();
		Transaction tx = pm.currentTransaction();
		tx.begin();
		if (!updatePass) {
			// Commuter foundEntity = em.find(Commuter.class, entity.getId());
			Commuter foundEntity = pm.getObjectById(Commuter.class, //
					entity.getId());
			entity.setPasswordMd5(foundEntity.getPasswordMd5());
		}
		// entity = em.merge(entity);
		// em.persist(entity);
		pm.makePersistent(entity);
		tx.commit();
	}

	@Override
	public void deleteCommuter(String sessionId, String id)
			throws AuthException {
		// TODO Auto-generated method stub

	}

	@Override
	public List<CommuterDto> listCommuters(String sessionId)
			throws AuthException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public List<LatLonDto> listAllHabitOrigins(String sessionId)
			throws AuthException {

		// EntityManager em = EmFactory
		// .getEntityManager(getThreadLocalRequest());
		PersistenceManager pm = PmFactory.get().getPersistenceManager();
		try {
			// return listAllHabitOrigins(em);
			return listAllHabitOrigins(pm);

		} catch (IllegalAccessException e) {
			e.printStackTrace();
			throw new InvocationException(e.getMessage(), e);

		} catch (InvocationTargetException e) {
			e.printStackTrace();
			throw new InvocationException(e.getMessage(), e);

		} finally {
			// em.close();
			pm.close();
		}
	}

	private List<LatLonDto> listAllHabitOrigins(
	/* EntityManager em */PersistenceManager pm) //
			throws IllegalAccessException, InvocationTargetException {

		// Query nativeQ = em.createNativeQuery( //
		// "SELECT id, orig_lon, orig_lat " //
		// + "FROM commuting_habit", //
		// CommutingHabit.class);
		// List<CommutingHabit> habits = nativeQ.getResultList();

		Query query = pm.newQuery(CommutingHabit.class);
		List<CommutingHabit> habits = (List<CommutingHabit>) query.execute();

		List<LatLonDto> dtos = new ArrayList<LatLonDto>(habits.size());
		for (CommutingHabit habit : habits) {
			LatLon origin = habit.getOrigin();
			dtos.add(ConversionUtil.entityToDto(origin));
		}
		return dtos;
	}

	@Override
	public List<LatLonDto> listAllHabitDestinations(String sessionId)
			throws AuthException {

		// EntityManager em = EmFactory
		// .getEntityManager(getThreadLocalRequest());
		PersistenceManager pm = PmFactory.get().getPersistenceManager();
		try {
			// return listAllHabitDestinations(em);
			return listAllHabitDestinations(pm);

		} catch (IllegalAccessException e) {
			e.printStackTrace();
			throw new InvocationException(e.getMessage(), e);

		} catch (InvocationTargetException e) {
			e.printStackTrace();
			throw new InvocationException(e.getMessage(), e);

		} finally {
			// em.close();
			pm.close();
		}
	}

	private List<LatLonDto> listAllHabitDestinations(//
			/* EntityManager em */PersistenceManager pm) //
			throws IllegalAccessException, InvocationTargetException {

		// Query nativeQ = em.createNativeQuery( //
		// "SELECT id, dest_lon, dest_lat " //
		// + "FROM commuting_habit", //
		// CommutingHabit.class);
		// List<CommutingHabit> habits = nativeQ.getResultList();

		Query query = pm.newQuery(CommutingHabit.class);
		List<CommutingHabit> habits = (List<CommutingHabit>) query.execute();

		List<LatLonDto> dtos = new ArrayList<LatLonDto>(habits.size());
		for (CommutingHabit habit : habits) {
			LatLon dest = habit.getDestination();
			dtos.add(ConversionUtil.entityToDto(dest));
		}
		return dtos;
	}

}
